#pragma once
#include <queue>

namespace Xps
{
	// TEMPLATE CLASS concurrent_queue
	template<class _Ty,
	class _Container = std::queue<_Ty> >
	class concurrent_queue
	{	// FIFO concurrent_queue implemented with a container
	public:
		typedef concurrent_queue<_Ty, _Container> _Myt;
		typedef _Container container_type;
		typedef typename _Container::value_type value_type;
		typedef typename _Container::size_type size_type;
		typedef typename _Container::reference reference;
		typedef typename _Container::const_reference const_reference;

		concurrent_queue()
			: c()
		{	// construct with empty container
		}

		concurrent_queue(const _Myt& _Right)
			: c(_Right.c)
		{	// construct by copying _Right container
		}

		explicit concurrent_queue(const _Container& _Cont)
			: c(_Cont)
		{	// construct by copying specified container
		}

		_Myt& operator=(const _Myt& _Right)
		{	// assign by copying _Right
			c = _Right.c;
			return (*this);
		}

		bool empty() const
		{	// test if concurrent_queue is empty
			return (c.empty());
		}

		size_type size() const
		{	// return length of concurrent_queue
			return (c.size());
		}

		reference front()
		{	// return first element of mutable concurrent_queue
			return (c.front());
		}

		const_reference front() const
		{	// return first element of nonmutable concurrent_queue
			return (c.front());
		}

		reference back()
		{	// return last element of mutable concurrent_queue
			return (c.back());
		}

		const_reference back() const
		{	// return last element of nonmutable concurrent_queue
			return (c.back());
		}

		void push(const value_type& _Val)
		{	// insert element at beginning
			c.push(_Val);
		}

		value_type pop()
		{	// erase element at end
			value_type m_front = front();
			c.pop();
			return m_front;
		}

		const _Container& _Get_container() const
		{	// get reference to container
			return (c);
		}

		void swap(_Myt& _Right)
		{	// exchange contents with _Right
			c.swap(_Right.c);
		}

	protected:
		_Container c;	// the underlying container
	};
};